package com.example.pcapnative;

import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.ptr.PointerByReference;

import java.util.ArrayList;
import java.util.List;

public class PcapNativeMappings {
    static {
        Native.register(PcapNativeMappings.class, "wpcap");
    }
    static native int pcap_findalldevs(PointerByReference paramPointerByReference, PcapErrbuf paramPcapErrbuf);
//    static native int pcap_findalldevs_ex(PointerByReference paramPointerByReference, PcapErrbuf paramPcapErrbuf);


    public static class PcapErrbuf extends Structure {
        public byte[] buf = new byte[PCAP_ERRBUF_SIZE()];

        private static int PCAP_ERRBUF_SIZE() {
            return 256;
        }

        public int length() {
            return this.toString().length();
        }

        protected List<String> getFieldOrder() {
            List<String> list = new ArrayList();
            list.add("buf");
            return list;
        }

        public String toString() {
            return Native.toString(this.buf);
        }
    }

    public static class pcap_if extends Structure {
        public ByReference next;
        public String name;
        public String description;
        public pcap_addr.ByReference addresses;
        public int flags;

        public pcap_if() {
        }

        public pcap_if(Pointer p) {
            super(p);
            this.read();
        }

        protected List<String> getFieldOrder() {
            List<String> list = new ArrayList();
            list.add("next");
            list.add("name");
            list.add("description");
            list.add("addresses");
            list.add("flags");
            return list;
        }

        public static class ByReference extends pcap_if implements Structure.ByReference {
        }
    }

    public static class pcap_addr extends Structure {
        public ByReference next;
        public sockaddr.ByReference addr;
        public sockaddr.ByReference netmask;
        public sockaddr.ByReference broadaddr;
        public sockaddr.ByReference dstaddr;

        public pcap_addr() {
        }

        public pcap_addr(Pointer p) {
            super(p);
            this.read();
        }

        protected List<String> getFieldOrder() {
            List<String> list = new ArrayList();
            list.add("next");
            list.add("addr");
            list.add("netmask");
            list.add("broadaddr");
            list.add("dstaddr");
            return list;
        }

        public static class ByReference extends pcap_addr implements Structure.ByReference {
        }
    }

    public static class sockaddr extends Structure {
        public short sa_family;
        public byte[] sa_data = new byte[14];

        public sockaddr() {
        }

        public sockaddr(Pointer p) {
            super(p);
            this.read();
        }

        protected List<String> getFieldOrder() {
            List<String> list = new ArrayList();
            list.add("sa_family");
            list.add("sa_data");
            return list;
        }

        short getSaFamily() {
            return this.sa_family;
//                if (isWindowsType()) {
//                    return this.sa_family;
//                } else {
//                    return NativeMappings.NATIVE_BYTE_ORDER.equals(ByteOrder.BIG_ENDIAN) ? (short)(255 & this.sa_family) : (short)(255 & this.sa_family >> 8);
//                }
        }

        static boolean isWindowsType() {
            return !Platform.isMac() && !Platform.isFreeBSD() && !Platform.isOpenBSD() && !Platform.iskFreeBSD();
        }

        public static class ByReference extends sockaddr implements Structure.ByReference {
        }
    }
}
